package com.spacearcade.logic;

import java.util.ArrayList;

public class LogicModel {
	static int intances = 1;
	public final int ID = intances;
	public double x = 0;
	public double y = 0;
	public double width = 0;
	public double angle = 0;
	public double dx = 0;
	public double dy = 0;
	public double dAngle = 0;
	public double health = 100;
	public double shield = 100;
	public double mass = 1;
	protected Dot shieldCenter = new Dot(0, 0);
	public int radius = 10;
	public double gap = 1.0;
	public ArrayList<Dot> dots = new ArrayList<Dot>();
	private boolean enginePower = false;
	private boolean rotateLeft = false;
	private boolean rotateRigth = false;
	protected double engineAcc = 0.7;
	protected double engineRotateAcc = 0.1;
	protected double maxSpeed = 5.0;
	protected double maxRotateSpeed = 0.07;
	private double friction = 1;//0.99999999;

	public LogicModel() {
		intances++;
	}

	public Pair getShieldCenter() {
		return new Pair(shieldCenter.getX(x, angle), shieldCenter.getY(y, angle));
	}

	public void mooveForward() {
		x += dx;
		y += dy;
		angle = (angle + dAngle) % (Math.PI * 2);

		dAngle *= 0.99;
		dAngle = Math.abs(dAngle) <= maxRotateSpeed ? dAngle : maxRotateSpeed * Math.signum(dAngle);
		if (enginePower) {

			dx += engineAcc * Math.cos(angle);
			dy += engineAcc * Math.sin(angle);


			if (!(rotateLeft || rotateRigth)) {
				dAngle *= 0.4;
			}
		}
		if (rotateLeft) {
			dAngle -= engineRotateAcc;
		}
		if (rotateRigth) {
			dAngle += engineRotateAcc;
		}

		double alpha = Math.atan2(dy, dx);
		double sp = dx / Math.cos(alpha);
		if (sp > maxSpeed) {
			dx = maxSpeed * Math.cos(alpha);
			dy = maxSpeed * Math.sin(alpha);

//			dx = ddx + Math.sqrt(Math.abs(-dx + 5 + ddx) / 5) * Math.signum(dx);
//			dy = ddy + Math.sqrt(Math.abs(-dy + 5 + ddy) / 5) * Math.signum(dy);
		}


	}

	public void mooveBackward() {
		x -= dx;
		y -= dy;
		angle -= dAngle;
	}

	public ArrayList<Dot> meet(LogicModel other) {
// intersection by shields;
		double distance = Math.sqrt((this.getShieldCenter().x - other.getShieldCenter().x)
				* (this.getShieldCenter().x - other.getShieldCenter().x)
				+ (this.getShieldCenter().y - other.getShieldCenter().y)
				* (this.getShieldCenter().y - other.getShieldCenter().y));

		if (distance > this.radius + other.radius) {
			return null;
		}
// proximity by dots;

		distance = Double.MAX_VALUE;

		Dot mDot = null, mmDot = null;

		for (Dot dot : other.dots) {
			double dotX1 = dot.getX(other.x, other.angle);
			double dotY1 = dot.getY(other.y, other.angle);

			for (Dot ddot : this.dots) {
				double dotX2 = ddot.getX(this.x, this.angle);
				double dotY2 = ddot.getY(this.y, this.angle);

				if (distance > Math.sqrt((dotX1 - dotX2) * (dotX1 - dotX2) + (dotY1 - dotY2) * (dotY1 - dotY2))) {
					distance = Math.sqrt((dotX1 - dotX2) * (dotX1 - dotX2) + (dotY1 - dotY2) * (dotY1 - dotY2));
					mDot = dot;
					mmDot = ddot;
				}
			}
		}

		if (distance > Math.max(this.gap, other.gap)) {
			return null;
		}

// TO DO OR NOT: degeneracy of the triangles;

		ArrayList<Dot> list = new ArrayList<Dot>();
		list.add(mDot);
		list.add(mmDot);


		return (ArrayList<Dot>) list.clone();
	}

	public void accelerationOn() {
		enginePower = true;
	}

	public void accelerationOff() {
		enginePower = false;
	}
		public void rotareLeftOn() {
		rotateLeft = true;
	}

	public void rotareRightOn() {
		rotateRigth = true;
	}

	public void rotareLeftOff() {
		rotateLeft = false;
	}

	public void rotareRightOff() {
		rotateRigth = false;
	}

	public void kick(LogicModel j, Dot otherDot, Dot thisDot) {
		double nx = j.x + j.dx - this.x - this.dx,
				ny = j.y + j.dy - this.y - this.dy;

		double n = Math.sqrt(nx * nx + ny * ny);
		double cosU = nx / n;
		double sinU = ny / n;

		double rx = this.dx * cosU - this.dy * (-sinU);
		double ry = this.dx * (-sinU) + this.dy * cosU;
		double rx2 = j.dx * cosU - j.dy * (-sinU);
		double ry2 = j.dx * (-sinU) + j.dy * cosU;
		double _rx = ((this.mass - j.mass) * rx + 2 * j.mass * rx2)
				/ (this.mass + j.mass);
		double _rx2 = rx + _rx - rx2;
		rx = _rx;
		rx2 = _rx2;

		double vx = rx * cosU - ry * sinU;
		double vy = rx * sinU + ry * cosU;

		double betta = Math.atan2(vy, vx);

		double v = Math.abs(vx / Math.cos(betta));

		double alpha = Math.atan2(-thisDot.y, -thisDot.x);

		double vx1 = vx * Math.cos(alpha) - vy * Math.sin(alpha);
		double vy1 = vx * Math.sin(alpha) + vy * Math.cos(alpha);

		double gamma = Math.atan2(vy1, vx1);

		this.dx = v * Math.cos(gamma) * Math.cos(betta);
		this.dy = v * Math.cos(gamma) * Math.sin(betta);
		this.dAngle = v * Math.sin(alpha)
				/ Math.pow(thisDot.x * thisDot.x + thisDot.y * thisDot.y, 0.75);

		vx = rx2 * cosU - ry2 * sinU;
		vy = rx2 * sinU + ry2 * cosU;

		betta = Math.atan2(vy, vx);

		v = Math.abs(vx / Math.cos(betta));

		alpha = Math.atan2(-otherDot.y, -otherDot.x);

		vx1 = vx * Math.cos(alpha) - vy * Math.sin(alpha);
		vy1 = vx * Math.sin(alpha) + vy * Math.cos(alpha);

		gamma = Math.atan2(vy1, vx1);

		j.dx = v * Math.cos(gamma) * Math.cos(betta);
		j.dy = v * Math.cos(gamma) * Math.sin(betta);
		j.dAngle = v * Math.sin(alpha)
				/ Math.pow(otherDot.x * otherDot.x + otherDot.y * otherDot.y, 0.75);
	}

	public String toString() {
		return ID + "_Model";
	}


}
